package com.yonyou.pmclouds.inspectitem.service.rmiimpl;

import com.alibaba.druid.util.StringUtils;
import com.alibaba.dubbo.config.annotation.Service;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.bp.template.MultiInsertBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleUpdateBpTemplate;
import com.yonyou.pmclouds.basecom.entity.SuperVO;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.basecom.util.BeanHelper;
import com.yonyou.pmclouds.basecom.util.CommonFieldConst;
import com.yonyou.pmclouds.inspectitem.entity.InspectItemBillStatusConst;
import com.yonyou.pmclouds.inspectitem.entity.InspectItemVO;
import com.yonyou.pmclouds.inspectitem.mapper.InspectItemMapper;
import com.yonyou.pmclouds.inspectitem.process.InspectItemAddAfterProcess;
import com.yonyou.pmclouds.inspectitem.process.InspectItemAddBeforeProcess;
import com.yonyou.pmclouds.inspectitem.process.InspectItemUpdateAfterProcess;
import com.yonyou.pmclouds.inspectitem.process.InspectItemUpdateBeforeProcess;
import com.yonyou.pmclouds.inspectitem.rmiitf.InspectItemService;
import com.yonyou.pmclouds.measuredata.entity.MeasureDataVO;
import com.yonyou.pmclouds.measuredata.service.rmiitf.MeasureDataService;
import com.yonyou.pmclouds.picture.entity.PictureParamVO;
import com.yonyou.pmclouds.picture.rmiitf.PictureRemoteService;
import com.yonyou.pmclouds.procedure.entity.ProcedureRefVO;
import com.yonyou.pmclouds.procedure.entity.ProcedureVO;
import com.yonyou.pmclouds.procedure.rmiitf.ProcedureQuery;
import com.yonyou.pmclouds.reason.entity.ProblemReasonVO;
import com.yonyou.pmclouds.reason.rmiitf.ProblemReasonQuery;
import com.yonyou.pmclouds.workquality.entity.WorkqualityDetailVO;
import com.yonyou.pmclouds.workquality.mapper.WorkqualityDetailMapper;
import com.yonyou.pmclouds.workquality.service.rmiitf.WorkqualityQueryService;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.math.BigDecimal;
import java.util.*;

@Service(version = ApplicationConsts.APPLICATION_VERSION, interfaceClass = InspectItemService.class)
public class InspectItemServiceImpl implements InspectItemService {
    @Autowired
    private InspectItemMapper mapper;
    @Autowired
    private InspectItemAddAfterProcess addAfterProcess;
    @Autowired
    private InspectItemUpdateAfterProcess updateAfterProcess;
    @Autowired
    private PictureRemoteService picService;
    @Autowired
    private MeasureDataService measureService;
    @Autowired
    private ProcedureQuery proceQuery;
    @Autowired
    private ProblemReasonQuery reasonQuery;
    @Autowired
    private WorkqualityDetailMapper detailMapper;
    @Autowired
    private WorkqualityQueryService workqualityQueryService;

    private static String[] UPDATE_FIELDS = {InspectItemVO.BILLSTATUS, InspectItemVO.MEMO, InspectItemVO.PHOTOSTATUS, InspectItemVO.MEASURESTATUS};

    @Override
    public InspectItemVO[] add(InspectItemVO[] vos, SuperVO vo) throws BusinessException {
        if (ArrayUtils.isEmpty(vos)) {
            return null;
        }
        for (int i = 0; i < vos.length; i++) {
            vos[i].setSequence(i);
        }
        MultiInsertBpTemplate<InspectItemVO> bp = new MultiInsertBpTemplate<>(mapper);
        bp.addBeforeProcessor(new InspectItemAddBeforeProcess());
        //保存测量数据，并检查是否推送生成问题记录单
        bp.addAfterProcessor(addAfterProcess);
        bp.insert(vos);
        String billType = (String) BeanHelper.getProperty(vo, CommonFieldConst.BILL_TYPE);
        if (billType == null) {
            billType = (String) BeanHelper.getProperty(vo, CommonFieldConst.BILLTYPE);
        }
        //图片保存
        PictureParamVO paramVO = new PictureParamVO(vos[0].getPk_bill(), vos[0].getPk_project(), billType);
        picService.insertBodyPictureForPub(vos, paramVO);
        return vos;
    }

    @Override
    public InspectItemVO[] update(InspectItemVO[] vos, SuperVO vo) throws BusinessException {
        if (ArrayUtils.isEmpty(vos)) {
            return null;
        }
        SingleUpdateBpTemplate<InspectItemVO> bp = new SingleUpdateBpTemplate<>(mapper, UPDATE_FIELDS);
        bp.addBeforeProcessor(new InspectItemUpdateBeforeProcess());
        bp.addAfterProcessor(updateAfterProcess);
        for(InspectItemVO itemVO : vos){
            bp.update(itemVO);
        }
        String billType = (String) BeanHelper.getProperty(vo, CommonFieldConst.BILL_TYPE);
        if (billType == null) {
            billType = (String) BeanHelper.getProperty(vo, CommonFieldConst.BILLTYPE);
        }
        for(InspectItemVO inspectItemVO : vos){
            if(inspectItemVO.isModified()){
                //更新单据图片
                PictureParamVO paramVO = new PictureParamVO(vos[0].getPk_bill(), vos[0].getPk_project(), billType);
                picService.updateBillPicture(inspectItemVO, paramVO);
            }
        }
        return vos;
    }

    @Override
    public InspectItemVO[] queryByPkbill(String pk_bill) throws BusinessException {
        if (StringUtils.isEmpty(pk_bill)) {
            return null;
        }
        return mapper.selectByBill(pk_bill);
    }

    @Override
    public InspectItemVO[] queryByPkBillsAndStatus(String[] pkBills, Integer status) throws BusinessException {
        if (ArrayUtils.isEmpty(pkBills)) {
            return new InspectItemVO[0];
        }
        return mapper.queryByPkBillsAndStatus(pkBills, status);
    }

    @Override
    public InspectItemVO queryOne(String pk_inspectitem) throws BusinessException {
        InspectItemVO itemVO = mapper.getById(pk_inspectitem);
        // 照片 TODO
        String[] picNames = picService.queryPicNamesByPkEntity(pk_inspectitem);
        itemVO.setPictures(picNames);
//        查询测量数据
        MeasureDataVO[] dataVOs = measureService.queryByPkbill(pk_inspectitem);
        itemVO.setDatas(extractData(dataVOs));
//         特殊数据存储
        itemVO.setMeasureData(dataVOs);
//         查询详情时，处理所有的参照字段
        return setRefFiledInfo(itemVO);
//        TODO
//        if (itemVO==null){
//            System.err.println("jjhdshfj为空");
//        }else {
//            System.err.println("=============="+itemVO.toString()+"==============");
//        }
//        return itemVO;
    }

    /**
     * 提取数据
     *
     * @param dataVOs
     * @return
     */
    private Double[] extractData(MeasureDataVO[] dataVOs) {
        if (ArrayUtils.isEmpty(dataVOs)) {
            return new Double[0];
        }
        Double[] datas = new Double[dataVOs.length];
        for (int i = 0; i < dataVOs.length; i++) {
            datas[i] = dataVOs[i].getNumber();
        }
        return datas;
    }

    /**
     * 施工记录合格率(%)
     *
     * @param constructLogPks
     * @return
     * @throws BusinessException
     */
    @Override
    public Map<String, BigDecimal> queryPassRateOfConstructLog(String[] constructLogPks) throws BusinessException {
        if (constructLogPks == null || constructLogPks.length == 0) {
            return new HashMap<>();
        }
        // 获取所有施工记录对应的所有检查项
        InspectItemVO[] inspectItemVOS = mapper.queryByConstructPks(constructLogPks);
        // 按施工记录分拣
        Map<String, List<InspectItemVO>> itemVOMap = new HashMap<>();
        for (InspectItemVO itemVO : inspectItemVOS) {
            if (itemVOMap.get(itemVO.getPk_bill()) == null) {
                List<InspectItemVO> itemVOList = new ArrayList<>();
                itemVOList.add(itemVO);
                itemVOMap.put(itemVO.getPk_bill(), itemVOList);
            } else {
                itemVOMap.get(itemVO.getPk_bill()).add(itemVO);
            }
        }
        // 分拣后，为每一组计算出合格率
        Map<String, BigDecimal> result = new HashMap<>();
        for (String pk : itemVOMap.keySet()) {
            // 通过数
            double passNum = 0;
            double total = 0;
            for (InspectItemVO inspectItemVO : itemVOMap.get(pk)) {
                if (InspectItemBillStatusConst.BILLSTATUS_NOT_FIT != inspectItemVO.getBillstatus()) {
                    total++;
                }
                if (InspectItemBillStatusConst.BILLSTATUS_PASS == inspectItemVO.getBillstatus()) {
                    passNum++;
                }
            }
            if (total == 0) {
                continue;
            }
            result.put(pk, new BigDecimal(((passNum / total) * 100)).setScale(2, BigDecimal.ROUND_HALF_UP));
        }
        return result;
    }

    /**
     * 批量检查项数据的获取和必要数据填充
     *
     * @param inspectItemPks
     * @return com.yonyou.pmclouds.inspectitem.entity.InspectItemVO[]
     * @author yzx
     * @date 2018/6/5 10:59
     */
    @Override
    public InspectItemVO[] queryInspectItemsInfoByPks(String[] inspectItemPks) throws BusinessException {
        if (inspectItemPks == null || inspectItemPks.length == 0) {
            return new InspectItemVO[0];
        }
        // 根据检查项pks,获取全部检查项数据
        InspectItemVO[] inspectItemVOS = mapper.queryByPks(inspectItemPks);
        // 照片
        Map<String, List<String>> picsMap = picService.queryPicsByPkEntitys(inspectItemPks);
        // 数据
        Map<String, List<MeasureDataVO>> measureMap = measureService.getPkBillsMap(inspectItemPks);
        // 检查项信息
        String[] itemPks = new String[inspectItemVOS.length];
        for (int i = 0; i < inspectItemVOS.length; i++) {
            itemPks[i] = inspectItemVOS[i].getPk_item();
        }
        WorkqualityDetailVO[] workqualityDetailVOS = null;
        if (itemPks.length > 0) {
            workqualityDetailVOS = detailMapper.queryByPks(itemPks);
        } else {
            workqualityDetailVOS = new WorkqualityDetailVO[0];
        }
        // 收集欲填充字段所有pk
        Set<String> procedurePks = new HashSet<>();
        for (InspectItemVO inspectItemVO : inspectItemVOS) {
            procedurePks.add(inspectItemVO.getPk_process());
        }
        // 查询所有工序
        Map<String, ProcedureRefVO> procedureRefVOMap = proceQuery.queryRefs(procedurePks.toArray(new String[procedurePks.size()]));
        // 赋值
        for (InspectItemVO inspectItemVO : inspectItemVOS) {
            // 图片
            if (picsMap != null && picsMap.get(inspectItemVO.getPk_inspectitem()) != null) {
                inspectItemVO.setPictures(picsMap.get(inspectItemVO.getPk_inspectitem()).toArray(new String[0]));
            }
            // 数据
            List<MeasureDataVO> dataVOS = measureMap.get(inspectItemVO.getPk_inspectitem());
            if (dataVOS != null) {
                Double[] datas = new Double[dataVOS.size()];
                for (int i = 0; i < dataVOS.size(); i++) {
                    datas[i] = dataVOS.get(i).getNumber();
                }
                inspectItemVO.setDatas(datas);
            }
            // 检查项信息
            for (WorkqualityDetailVO detailVO : workqualityDetailVOS) {
                if (inspectItemVO.getPk_item().equals(detailVO.getPkWorkqualitydetail())) {
                    inspectItemVO.setItem_name(detailVO.getCheckitem());
                    inspectItemVO.setItem_content(detailVO.getCheckdescription());
                }
            }
            if (procedureRefVOMap.get(inspectItemVO.getPk_process()) != null) {
                // 工序
                inspectItemVO.setProcess_name(procedureRefVOMap.get(inspectItemVO.getPk_process()).getSname());
            }
        }
        return inspectItemVOS;
    }

    /**
     * 处理工序、问题原因
     *
     * @param vo
     * @return
     * @throws BusinessException
     */
    private InspectItemVO setRefFiledInfo(InspectItemVO vo) throws BusinessException {
        // 工序
        String pk_process = vo.getPk_process();
        String pk_problemreason = vo.getPk_problemreason();
        if (!StringUtils.isEmpty(pk_process)) {
            ProcedureVO procedureVO = proceQuery.getById(pk_process);
            vo.setProcess_name(procedureVO.getSname());

        }
        //TODO：问题原因
        if (!StringUtils.isEmpty(pk_problemreason)) {
            ProblemReasonVO reasonVO = reasonQuery.getById(pk_problemreason);
            vo.setProblemreason_name(reasonVO.getSname());
        }
        // 检查项目相关信息
        String pkItem = vo.getPk_item();
        WorkqualityDetailVO workqualityDetailVO = detailMapper.queryById(pkItem);
        if (workqualityDetailVO != null) {
            vo.setItem_name(workqualityDetailVO.getCheckitem());
            vo.setItem_content(workqualityDetailVO.getCheckdescription());
        }
        return vo;
    }
}
